#pragma once


#include <iostream>
#include <string>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstring>
#include <jsoncpp/json/json.h>

namespace ns_protocol
{
// #define MYSELF 0
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n"
#define SEP_LEN strlen(SEP)//不能是sizeof
    
    class Request
    {
    public:
        //1.自主实现"length\r\n_x _op _y\r\n"
        //2.使用现成的方案
        std::string Serialize()
        {
#ifdef MYSELF
            std::string str;
            str = std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);
            return str;

#else
            Json::Value root;//万能对象，可以定义和保存任意对象
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer;
            return writer.write(root);

#endif

        }

        //"_x _op _y"
        bool Deserialized(const std::string& str)
        {
#ifdef MYSELF
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos)
                return false;
            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;
            _x = atoi(str.substr(0, left).c_str());
            _y = atoi(str.substr(right + SPACE_LEN).c_str());
            if (left + SPACE_LEN > str.size())
                return false;
            else
                _op = str[left + SPACE_LEN];
            return true;

#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
            return true;

#endif
        }

    public:
        Request()
        {}

        Request(int x, int y, char op)
            :_x(x),
            _y(y),
            _op(op)
        {}

        ~Request()
        {}
    public:
        int _x;
        int _y;
        char _op;// + - * / %
    };

    class Response
    {
    public:
        //"_code _result"
        std::string Serialize()
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(_code);
            s += SPACE;
            s += std::to_string(_result);

            return s;


#else
            Json::Value root;
            root["code"] = _code;
            root["result"] = _result;
            root["xx"] = _x;
            root["yy"] = _y;
            root["zz"] = _op;
            Json::FastWriter writer;
            return writer.write(root);

#endif

        }

        bool Deserialized(const std::string& s)
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;
            _code = atoi(s.substr(0, pos).c_str());
            _result = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;


#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(s, root);
            _code = root["code"].asInt();
            _result = root["result"].asInt();
            _x = root["xx"].asInt();
            _y = root["yy"].asInt();
            _op = root["zz"].asInt();
            return true;
            
#endif
        }

    public:
        Response()
        {}

        Response(int result, int code, int x, int y, char op)
            :_result(result),
            _code(code),
            _x(x),
            _y(y),
            _op(op)
        {}

        ~Response()
        {}
    public:
        int _result;//计算结果
        int _code;//计算结果的状态码

        int _x;
        int _y;
        char _op;
    };


    //期望Recv，必须返回一个完整的报文
    bool Recv(int sock, std::string* out)
    {
        //UDP面向数据报的
        //TCP面向字节流的
        //recv无法保证读到的inbuffer，是一个完整完善的请求
        //单纯的recv是无法解决这个问题的，所以需要对协议进一步定制
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer), 0);
        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if (s == 0)
        {
            // std::cout << "client quit" << std::endl;
            return false;
        }
        else
        {
            // std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }


    void Send(int sock, const std::string str)
    {
        // std::cout << "send in" << std::endl;
        int n = send(sock, str.c_str(), str.size(), 0);
        if (n < 0)
        {
            std::cout << "send error" << std::endl;
        }
    }

    //"length\r\n_x _op _y\r\n..."
    std::string Decode(std::string& buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if (pos == std::string::npos)
        {
            return "";
        }

        int size = atoi(buffer.substr(0, pos).c_str());

        int surplus = buffer.size() - pos - SEP_LEN - SEP_LEN;

        if (surplus >= size)
        {
            //至少有一个完整合法的报文,可以提取了
            buffer.erase(0, pos + SEP_LEN);
            std::string s = buffer.substr(0, size);
            buffer.erase(0, size + SEP_LEN);
            return s;

        }
        else
        {
            return "";
        }
    }

    std::string Encode(std::string& s)
    {
        std::string new_package = std::to_string(s.size());
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }



}